using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.SharePoint;
using System.ComponentModel;
using System.Globalization;
using System.Web.UI.WebControls.WebParts;
using TST.SharePoint.Shared;

namespace TST.WebParts
{
    public class WebPropertyFilter : WebPart, IWebEditable, Microsoft.SharePoint.WebPartPages.ITransformableFilterValues, Microsoft.SharePoint.WebPartPages.IDefaultFilterValue
    {
        private string _currentSiteProperty;
        private string _parentSiteProperty;
        private string _rootSiteProperty;
        private FilterMultipleValueHandling _multipleValueHandling;
        private Exception _exception;
        private String _valueSeparator;

        [Browsable(false),
        Personalizable(PersonalizationScope.Shared)]
        public string CurrentSiteProperty
        {
            get { return _currentSiteProperty; }
            set { _currentSiteProperty = value; } 
        }

        [Browsable(false),
        Personalizable(PersonalizationScope.Shared)]
        public string ParentSiteProperty
        {
            get { return _parentSiteProperty; }
            set { _parentSiteProperty = value; }
        }

        [Browsable(false),
        Personalizable(PersonalizationScope.Shared)]
        public string RootSiteProperty
        {
            get { return _rootSiteProperty; }
            set { _rootSiteProperty = value; }
        }

        [Browsable(false),
        Personalizable(PersonalizationScope.Shared)]
        public FilterMultipleValueHandling MultipleValueHandling
        {
            get { return _multipleValueHandling; }
            set { _multipleValueHandling = value; }
        }
        
        [Browsable(false),
        Personalizable(PersonalizationScope.Shared)]
        public string ValueSeparator
        {
            get { return _valueSeparator; }
            set { _valueSeparator = value; }
        }

        private String DesignTimeHtml
        {
            get
            {
                string result = string.Empty;
                if (string.IsNullOrEmpty(CurrentSiteProperty) && string.IsNullOrEmpty(ParentSiteProperty) && string.IsNullOrEmpty(RootSiteProperty))
                {
                    result = "Please select one of the properties in the web part toolpane.";
                    return result;
                }
                if (!string.IsNullOrEmpty(CurrentSiteProperty))
                {
                    result = string.Format(" This webpart sends the value of '{0}' of the current site to connected webparts.", CurrentSiteProperty);
                }
                if (!string.IsNullOrEmpty(ParentSiteProperty))
                {
                    result += string.Format(" This webpart sends the value of '{0}' of the parent site to connected webparts.", ParentSiteProperty);
                }
                if (!string.IsNullOrEmpty(RootSiteProperty))
                {
                    result += string.Format(" This webpart sends the value of '{0}' of the root site to connected webparts.", RootSiteProperty);
                }
                switch (this.MultipleValueHandling)
                {
                    case FilterMultipleValueHandling.Combine:
                        result += string.Format(" If multiple properties are selected, the values will be combined to 1 single value, separated by a '{0}'", this.ValueSeparator);
                        break;
                    case FilterMultipleValueHandling.SendAll:
                        result += " If multiple properties are selected, all values will be sent.";
                        break;
                    case FilterMultipleValueHandling.SendFirst:
                        result += " If multiple properties are selected, just the first property value will be sent.";
                        break;
                }
                return result;
            }
        }

        private bool FilterConfigured
        {
            get
            {
                return (!string.IsNullOrEmpty(CurrentSiteProperty) || !string.IsNullOrEmpty(ParentSiteProperty) || !string.IsNullOrEmpty(RootSiteProperty));
            }
        }

        protected override void RenderContents(System.Web.UI.HtmlTextWriter writer)
        {
            base.RenderContents(writer);
            if (!FilterConfigured)
            {
                writer.WriteLine(BaseDataWebPart.GetOpenToolPaneText("This webpart is not yet configured", this.ID));
            }
            else
            {
                writer.WriteLine(DesignTimeHtml);
            }
            // Error handling
            if (_exception != null)
            {
                writer.WriteLine(string.Format("Error: {0}", _exception.Message));
            }
        }

        protected override void OnPreRender(EventArgs e)
        {
            base.OnPreRender(e);
            if (HideWebPart)
            {
                Hidden = true;
                ChromeType = PartChromeType.None;
            }
        }

        private bool HideWebPart
        {
            get
            {
                return base.WebPartManager != null && !base.WebPartManager.DisplayMode.AllowPageDesign;
            }
        }

        [ConnectionProvider(
        "default value",
        "UniqueIDForWebPropertyFilterDefaultValueConnection",
        AllowsMultipleConnections = true)]
        public Microsoft.SharePoint.WebPartPages.IDefaultFilterValue SetDefaultValueConnection()
        {
            return this;
        }

        [ConnectionProvider(
        "filter value",
        "UniqueIDForWebPropertyFilterFilterValueConnection",
        AllowsMultipleConnections = true)]
        public Microsoft.SharePoint.WebPartPages.ITransformableFilterValues SetFilterConnection()
        {
            return this;
        }

        #region IWebEditable Members

        EditorPartCollection IWebEditable.CreateEditorParts()
        {
            List<EditorPart> newEditors = new List<EditorPart>();

            EditorPartCollection editors = base.CreateEditorParts();
            foreach (EditorPart part in editors)
                newEditors.Add(part);

            newEditors.Add(new SelectWebPropertyEditor(this.ID));

            return new EditorPartCollection(newEditors);
        }

        object IWebEditable.WebBrowsableObject
        {
            get { return this; }
        }

        #endregion

        #region IDefaultFilterValue Members

        public string DefaultValue
        {
            get
            {
                List<string> values = new List<string>();
                if (!string.IsNullOrEmpty(CurrentSiteProperty))
                {
                    string val = SelectWebPropertyEditor.GetValueForProperty(CurrentSiteProperty, SPContext.Current.Web);
                    if (!string.IsNullOrEmpty(val))
                    {
                        return val;
                    }
                }
                if (!string.IsNullOrEmpty(ParentSiteProperty) && (this.MultipleValueHandling != FilterMultipleValueHandling.SendFirst || values.Count == 0))
                {
                    using (SPWeb parent = SPContext.Current.Web.ParentWeb)
                    {
                        if (parent != null)
                        {
                            string val = SelectWebPropertyEditor.GetValueForProperty(ParentSiteProperty, parent);
                            if (!string.IsNullOrEmpty(val))
                            {
                                return val;
                            }
                        }
                    }
                }
                if (!string.IsNullOrEmpty(RootSiteProperty) && (this.MultipleValueHandling != FilterMultipleValueHandling.SendFirst || values.Count == 0))
                {
                    SPWeb root = SPContext.Current.Site.RootWeb;
                    try
                    {
                        string val = SelectWebPropertyEditor.GetValueForProperty(RootSiteProperty, root);
                        if (!string.IsNullOrEmpty(val))
                        {
                            return val;
                        }
                    }
                    finally
                    {
                        if (root.ID != SPContext.Current.Web.ID)
                        {
                            root.Dispose();
                        }
                    }
                }
                return null;
            }
        }

        #endregion

        #region ITransformableFilterValues Members

        public bool AllowAllValue
        {
            get { return false; }
        }

        public bool AllowEmptyValue
        {
            get { return false; }
        }

        public bool AllowMultipleValues
        {
            get { return true; }
        }

        public string ParameterName
        {
            get { return "FilterValue"; }
        }

        public System.Collections.ObjectModel.ReadOnlyCollection<string> ParameterValues
        {
            get
            {
                List<string> values = new List<string>();
                if (!string.IsNullOrEmpty(CurrentSiteProperty))
                {
                    string val = SelectWebPropertyEditor.GetValueForProperty(CurrentSiteProperty, SPContext.Current.Web);
                    if (!string.IsNullOrEmpty(val))
                    {
                        values.Add(val);
                    }
                }
                if (!string.IsNullOrEmpty(ParentSiteProperty) && (this.MultipleValueHandling != FilterMultipleValueHandling.SendFirst || values.Count == 0))
                {
                    using (SPWeb parent = SPContext.Current.Web.ParentWeb)
                    {
                        if (parent != null)
                        {
                            string val = SelectWebPropertyEditor.GetValueForProperty(ParentSiteProperty, parent);
                            if (!string.IsNullOrEmpty(val))
                            {
                                values.Add(val);
                            }
                        }
                    }
                }
                if (!string.IsNullOrEmpty(RootSiteProperty) && (this.MultipleValueHandling != FilterMultipleValueHandling.SendFirst || values.Count == 0))
                {
                    SPWeb root = SPContext.Current.Site.RootWeb;
                    try
                    {
                        string val = SelectWebPropertyEditor.GetValueForProperty(RootSiteProperty, root);
                        if (!string.IsNullOrEmpty(val))
                        {
                            values.Add(val);
                        }
                    }
                    finally
                    {
                        if (root.ID != SPContext.Current.Web.ID)
                        {
                            root.Dispose();
                        }
                    }
                }
                if (values.Count > 0)
                {
                    if (values.Count == 1 || MultipleValueHandling == FilterMultipleValueHandling.SendAll)
                    {
                        System.Collections.ObjectModel.ReadOnlyCollection<string> parameterValues = new System.Collections.ObjectModel.ReadOnlyCollection<string>(values);
                        return parameterValues;
                    }
                    else if (MultipleValueHandling == FilterMultipleValueHandling.Combine)
                    {
                        string result = string.Empty;
                        foreach (string v in values)
                        {
                            result += string.Format("{0}{1}", v, ValueSeparator);
                        }
                        result = result.TrimEnd(ValueSeparator.ToCharArray());
                        System.Collections.ObjectModel.ReadOnlyCollection<string> parameterValues = new System.Collections.ObjectModel.ReadOnlyCollection<string>(values);
                        return parameterValues;
                    }
                }
                return null;
            }
        }

        #endregion

    }

    public enum FilterMultipleValueHandling
    {
        SendFirst = 0,
        SendAll = 1,
        Combine = 2,
    }
}
